using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace Easy521WPF
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// 汇川Easy521 Modbus TCP通讯主窗口
    /// </summary>
    public partial class MainWindow : Window
    {
        private ModbusTcpClient modbusClient;      // Modbus TCP客户端对象
        private DispatcherTimer autoReadTimer;     // 自动读取定时器
        private bool isConnected = false;          // 连接状态标志

        // X输入指示灯数组
        private Ellipse[] xLights;
        // Y输出指示灯数组
        private Ellipse[] yLights;

        /// <summary>
        /// 构造函数
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            // 初始化Modbus客户端
            modbusClient = new ModbusTcpClient();

            // 初始化自动读取定时器
            autoReadTimer = new DispatcherTimer();
            autoReadTimer.Interval = TimeSpan.FromMilliseconds(500);  // 500ms间隔
            autoReadTimer.Tick += AutoReadTimer_Tick;

            // 初始化指示灯数组
            InitializeLights();

            // 窗口关闭事件
            this.Closing += MainWindow_Closing;
        }

        /// <summary>
        /// 初始化指示灯数组
        /// </summary>
        private void InitializeLights()
        {
            // X输入指示灯
            xLights = new Ellipse[] { LightX0, LightX1, LightX2, LightX3, LightX4, LightX5, LightX6, LightX7 };

            // Y输出指示灯
            yLights = new Ellipse[] { LightY0, LightY1, LightY2, LightY3, LightY4, LightY5, LightY6, LightY7 };
        }

        /// <summary>
        /// 窗口关闭事件处理
        /// </summary>
        private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // 停止定时器
            if (autoReadTimer.IsEnabled)
                autoReadTimer.Stop();

            // 断开连接
            if (modbusClient.IsConnected)
                modbusClient.Disconnect();
        }

        /// <summary>
        /// 连接/断开按钮点击事件
        /// </summary>
        private void BtnConnect_Click(object sender, RoutedEventArgs e)
        {
            if (!isConnected)
            {
                // 执行连接操作
                try
                {
                    string ip = TxtIpAddress.Text.Trim();
                    int port = int.Parse(TxtPort.Text.Trim());
                    int timeout = int.Parse(TxtTimeout.Text.Trim()) * 1000; // 转换为毫秒

                    modbusClient.Connect(ip, port, timeout);
                    isConnected = true;

                    BtnConnect.Content = "断开";
                    BtnConnect.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#f44336"));
                    TxtStatus.Text = "状态: 已连接";
                    TxtStatus.Foreground = new SolidColorBrush(Colors.Green);

                    LogMessage($"已连接到 {ip}:{port}");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"连接失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    LogMessage($"连接失败: {ex.Message}");
                }
            }
            else
            {
                // 执行断开操作
                try
                {
                    // 停止自动读取
                    if (autoReadTimer.IsEnabled)
                    {
                        autoReadTimer.Stop();
                        ChkAutoRead.IsChecked = false;
                    }

                    modbusClient.Disconnect();
                    isConnected = false;

                    BtnConnect.Content = "连接";
                    BtnConnect.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4CAF50"));
                    TxtStatus.Text = "状态: 未连接";
                    TxtStatus.Foreground = new SolidColorBrush(Colors.Black);

                    LogMessage("已断开连接");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"断开失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// 自动读取复选框选中事件
        /// </summary>
        private void ChkAutoRead_Checked(object sender, RoutedEventArgs e)
        {
            if (isConnected)
            {
                autoReadTimer.Start();
                LogMessage("已启用自动读取");
            }
            else
            {
                ChkAutoRead.IsChecked = false;
                MessageBox.Show("请先连接到PLC", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }

        /// <summary>
        /// 自动读取复选框取消选中事件
        /// </summary>
        private void ChkAutoRead_Unchecked(object sender, RoutedEventArgs e)
        {
            autoReadTimer.Stop();
            LogMessage("已停止自动读取");
        }

        /// <summary>
        /// 自动读取定时器Tick事件
        /// </summary>
        private void AutoReadTimer_Tick(object sender, EventArgs e)
        {
            ReadAllStatus();
        }

        /// <summary>
        /// 读取所有X和Y状态
        /// </summary>
        private void ReadAllStatus()
        {
            if (!isConnected) return;

            try
            {
                // 读取X输入状态 (功能码02, 地址0xF800, 读取8个点)
                bool[] xStatus = modbusClient.ReadDiscreteInputs(0xF800, 8);
                if (xStatus != null)
                {
                    for (int i = 0; i < 8 && i < xStatus.Length; i++)
                    {
                        UpdateLight(xLights[i], xStatus[i]);
                    }
                }

                // 读取Y输出状态 (功能码01, 地址0xFC00, 读取8个点)
                bool[] yStatus = modbusClient.ReadCoils(0xFC00, 8);
                if (yStatus != null)
                {
                    for (int i = 0; i < 8 && i < yStatus.Length; i++)
                    {
                        UpdateLight(yLights[i], yStatus[i]);
                    }
                }
            }
            catch (Exception ex)
            {
                LogMessage($"读取状态错误: {ex.Message}");
            }
        }

        /// <summary>
        /// 更新指示灯状态
        /// </summary>
        /// <param name="light">指示灯控件</param>
        /// <param name="state">状态(true为亮，false为灭)</param>
        private void UpdateLight(Ellipse light, bool state)
        {
            if (state)
            {
                // 亮灯 - 绿色
                light.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#00FF00"));
                light.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#008000"));
            }
            else
            {
                // 灭灯 - 灰色
                light.Fill = new SolidColorBrush(Colors.Gray);
                light.Stroke = new SolidColorBrush(Colors.Black);
            }
        }

        /// <summary>
        /// Y输出指示灯点击事件 - 切换单个Y输出
        /// </summary>
        private void LightY_Click(object sender, MouseButtonEventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("请先连接到PLC", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            Ellipse light = sender as Ellipse;
            if (light != null)
            {
                int yIndex = int.Parse(light.Tag.ToString());
                ushort address = (ushort)(0xFC00 + yIndex);

                try
                {
                    // 读取当前状态
                    bool[] currentStatus = modbusClient.ReadCoils(address, 1);
                    bool newState = currentStatus != null ? !currentStatus[0] : true;

                    // 写入新状态
                    modbusClient.WriteSingleCoil(address, newState);
                    LogMessage($"Y{yIndex} 已设置为 {(newState ? "开启" : "关闭")}");

                    // 立即读取状态更新显示
                    ReadAllStatus();
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"操作失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    LogMessage($"Y{yIndex} 操作失败: {ex.Message}");
                }
            }
        }

        /// <summary>
        /// 写入单个寄存器按钮点击事件
        /// </summary>
        private void BtnWriteRegister_Click(object sender, RoutedEventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("请先连接到PLC", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                ushort address = ushort.Parse(TxtWriteRegAddr.Text.Trim());
                ushort value = ushort.Parse(TxtWriteRegValue.Text.Trim());

                modbusClient.WriteSingleRegister(address, value);
                LogMessage($"成功写入 D{address} = {value}");
                MessageBox.Show($"成功写入 D{address} = {value}", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (FormatException)
            {
                MessageBox.Show("请输入有效的数字", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                LogMessage($"写入寄存器失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 读取寄存器按钮点击事件
        /// </summary>
        private void BtnReadRegisters_Click(object sender, RoutedEventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("请先连接到PLC", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                ushort startAddress = ushort.Parse(TxtReadRegStart.Text.Trim());
                ushort count = ushort.Parse(TxtReadRegCount.Text.Trim());

                ushort[] values = modbusClient.ReadHoldingRegisters(startAddress, count);

                if (values != null)
                {
                    string result = "";
                    for (int i = 0; i < values.Length; i++)
                    {
                        result += $"D{startAddress + i}={values[i]} ";
                    }
                    TxtRegResult.Text = result.TrimEnd();
                    LogMessage($"读取寄存器成功: {result}");
                }
                else
                {
                    TxtRegResult.Text = "读取失败";
                    LogMessage("读取寄存器失败");
                }
            }
            catch (FormatException)
            {
                MessageBox.Show("请输入有效的数字", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"读取失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                LogMessage($"读取寄存器失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 按地址写单个数字量按钮点击事件
        /// </summary>
        private void BtnWriteSingleCoil_Click(object sender, RoutedEventArgs e)
        {
            if (!isConnected)
            {
                MessageBox.Show("请先连接到PLC", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                // 解析地址(支持十六进制，如FC00)
                string addrText = TxtSingleCoilAddr.Text.Trim().ToUpper();
                ushort address = Convert.ToUInt16(addrText, 16);

                // 获取状态
                bool state = CmbCoilState.SelectedIndex == 1; // 0=关闭, 1=开启

                modbusClient.WriteSingleCoil(address, state);
                LogMessage($"成功写入地址 0x{address:X4} = {(state ? "开启" : "关闭")}");
                MessageBox.Show($"成功写入地址 0x{address:X4} = {(state ? "开启" : "关闭")}", "成功",
                    MessageBoxButton.OK, MessageBoxImage.Information);

                // 立即读取状态更新显示
                ReadAllStatus();
            }
            catch (FormatException)
            {
                MessageBox.Show("请输入有效的十六进制地址(如:FC00)", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"写入失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                LogMessage($"写入数字量失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清除日志按钮点击事件
        /// </summary>
        private void BtnClearLog_Click(object sender, RoutedEventArgs e)
        {
            TxtLog.Text = "";
        }

        /// <summary>
        /// 添加日志消息
        /// </summary>
        /// <param name="message">消息内容</param>
        private void LogMessage(string message)
        {
            string timeStamp = DateTime.Now.ToString("HH:mm:ss.fff");
            TxtLog.Text += $"[{timeStamp}] {message}\r\n";

            // 自动滚动到底部
            TxtLog.ScrollToEnd();
        }
    }
}
